package sql;

import config.Config;
import entity.ColumnDefine;
import entity.IndexDefine;
import entity.PKColumnDefine;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.parsing.PropertyParser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class SqlGenerator {
	
	public class Response{
		private String sql;
		private String message;
		
		public String getSql() {
			return sql;
		}
		public void setSql(String sql) {
			this.sql = sql;
		}
		
		public String getMessage() {
			return message;
		}
		public void setMessage(String message) {
			this.message = message;
		}
	}
	
	private Config config;
	
	public SqlGenerator(Config config){
		this.config = config;
	}
	
	public Response genQueryTableSql(){
		Response rep = new Response();
		rep.setSql(config.getSqlTplQueryTableNames());
		return rep;
	}
	
	public Response genQueryPkColumnsSql(String tableName){
		Response rep = new Response();
		Properties variables = new Properties();
		variables.put("tableName", tableName);
		rep.setSql(PropertyParser.parse(config.getSqlTplQueryPkColumns(), variables));
		return rep;
	}
	
	public Response genQueryColumnsSql(String tableName){
		Response rep = new Response();
		Properties variables = new Properties();
		variables.put("tableName", tableName);
		rep.setSql(PropertyParser.parse(config.getSqlTplQueryColumns(), variables));
		return rep;
	}
	
	public Response genCreateColumnCommentsSql(String tableName,ColumnDefine column){
		Response rep = new Response();
		String field = column.getColumnName();
		String comment = column.getComments() == null ? "" : column.getComments().replaceAll("'", "''");
		if(comment.length() > 50){
			rep.setMessage(column.getColumnName() + String.format("：列注释超过100字符，自动截断，原注释为：%s  ", comment));
			comment = comment.substring(0, 50);
		}
		Properties variables = new Properties();
		variables.put("tableName", tableName);
		variables.put("comments", comment);
		variables.put("field", field);
		rep.setSql(PropertyParser.parse(config.getSqlTplCreateComments(), variables));
		return rep;
	}
	
	public Response genCreateColumnDefineSql(ColumnDefine column, String tableName){
		Response rep = new Response();
		String dbType = config.getTargetDbType(column.getDataType());
		String targetDbType = dbType;
		StringBuilder waringMessage = new StringBuilder();
		if(dbType.equals("CHARACTER") && column.getDataLength() != null && column.getDataLength() > 254){
			targetDbType = "VARCHAR";
			waringMessage.append(column.getColumnName() + "：CHARACTER的length超过254,类型自动转成VARCHAR  ");
		}
		else if (column.getDataPrecision() != null && column.getDataPrecision() > 0) {
			// 数值型
			int precision = column.getDataPrecision() > 31 ? 31 : column.getDataPrecision();
			if(column.getDataPrecision() > 31){
				waringMessage.append(column.getColumnName() + "：precision的length超过31,自动截成31  ");
			}
			if (column.getDataScale() != null && column.getDataScale() > 0) {
				targetDbType = String.format("%s(%d,%d)", targetDbType, precision, column.getDataScale());
			} else {
				targetDbType = String.format("%s(%d)", targetDbType, precision);
			}
		} else {
			if(column.getDataType().equals("CLOB")){
				targetDbType = String.format("%s", targetDbType);
			}
			else if (column.getDataLength() != null && column.getDataLength() > 0) {
				targetDbType = String.format("%s(%d)", targetDbType, column.getDataLength());
			}
		}
		
		String nullable = column.getNullable().equals("N") ? "not null" : "";
		String defaultValue = column.getDataDefault() != null && column.getDataDefault().length() > 0
				? "default " + column.getDataDefault() : "";
		String comment = column.getComments() == null ? "" : column.getComments().replaceAll("'", "''");
		if(comment.length() > 50){
			rep.setMessage(column.getColumnName() + String.format("：列注释超过100字符，自动截断，原注释为：%s  ", comment));
			comment = comment.substring(0, 50);
		}
		Properties variables = new Properties();
		variables.put("field", column.getColumnName());
		variables.put("dbtype", targetDbType);
		variables.put("nullable", nullable);
		variables.put("defaultvalue",
				defaultValue.toUpperCase().indexOf("TO_CHAR") >= 0 || defaultValue.toUpperCase().indexOf("SYSDATE") >= 0 ? ""
						: defaultValue.replace("(", "").replace(")", ""));
		variables.put("comments", comment);
		if(defaultValue.toUpperCase().indexOf("TO_CHAR") >= 0 || defaultValue.toUpperCase().indexOf("SYSDATE") >= 0){
			waringMessage.append(column.getColumnName() + String.format("：%s不支持的defaultvalue，自动跳过设置默认值   ", defaultValue));
		}
		rep.setSql(String.format("%s", PropertyParser.parse(config.getSqlTplColumnDefine(), variables)));
		rep.setMessage(waringMessage.toString());
		return rep;
	}
	
	
	public Response genCreateTableSql(String tableName,String sql4ColumnsDefine){
		Response rep = new Response();
		Properties variables = new Properties();
		variables.put("tableName", tableName);
		variables.put("columns", sql4ColumnsDefine);
		String tableComments = SqlExecutor.getInstance().QueryTableComments(tableName);
		if(StringUtils.isNotBlank(tableComments)){
			//加上表名的注释
			variables.put("tableComments", tableComments);
		}else{
			variables.put("tableComments", "");
		}
		rep.setSql(PropertyParser.parse(config.getSqlTplCreateTable(), variables));
		return rep;
	}
	
	public Response genCreatePkConstraintSql(String tableName,List<PKColumnDefine> pkColumns){
		Response rep = new Response();
		List<String> columns = new ArrayList<String>();
		for(PKColumnDefine pk : pkColumns){
			columns.add(pk.getColumnName());
		}
		Properties variables = new Properties();
		variables.put("tableName", tableName);
		variables.put("columns", StringUtils.join(columns,","));
		variables.put("pkName", pkColumns.get(0).getPkName());
	    rep.setSql(PropertyParser.parse(config.getSqlTplCreatePk(), variables));
	    return rep;
	}
	
	public Response genQueryIndexSql(String tableName){
		Response rep = new Response();
		Properties variables = new Properties();
		variables.put("tableName", tableName);
		rep.setSql(PropertyParser.parse(config.getSqlTplQueryIndex(), variables));
		return rep;
	}
	
	public List<Response> genCreateIndexSql(String tableName,List<IndexDefine> indexs){
		Map<String,List<IndexDefine>> map = new HashMap<String, List<IndexDefine>>();
		List<Response> reps = new ArrayList<SqlGenerator.Response>();
		
		for(IndexDefine define : indexs){
			if(!map.containsKey(define.getIndexName())){
				map.put(define.getIndexName(), new ArrayList<IndexDefine>());
			}
			
			map.get(define.getIndexName()).add(define);
		}
		
		for(String indexName : map.keySet()){
			List<IndexDefine> ids = map.get(indexName);
			Properties variables = new Properties();
			variables.put("tableName", tableName);
			variables.put("indexName", indexName);
			variables.put("uniqueable", ids.get(0).getUniqueness().equals("UNIQUE") ? "UNIQUE" : "");
			List<String> sql4IndexDefine = new ArrayList<String>();
			for(IndexDefine index : ids){
				sql4IndexDefine.add(String.format("%s %s ", index.getColumnName(),index.getDescend()));
			}
			variables.put("columns", StringUtils.join(sql4IndexDefine,","));
			Response rep = new Response();
			rep.setSql(PropertyParser.parse(config.getSqlTplCreateIndex(), variables));
			reps.add(rep);
		}
		
		return reps;
	}
	
	public Response genQuerySequences(){
		Response rep = new Response();
		rep.setSql(config.getSqlTplQuerySequences());
		return rep;
	}
}
